﻿/********************************************************************
	created:	2016/04/07
	created:	7:4:2016   11:58
	filename: 	e:\XuanwuCode\branches\branches_gns\XuanwuClient\AllGame\GnsClientFrame\proj.win32\GnsPolygon2.h
	file path:	e:\XuanwuCode\branches\branches_gns\XuanwuClient\AllGame\GnsClientFrame\proj.win32
	file base:	GnsPolygon2
	file ext:	h
	author:		hgj
	
	purpose:	二维多边形
*********************************************************************/

#ifndef  GNS_POLYGON_2_H
#define GNS_POLYGON_2_H

#include "Mat44.h"
#include <vector>


struct MyPOINT
{
	float x;
	float y;
};

using std::vector;    // 污染小一些

class GnsPolygon2
{
public:
	GnsPolygon2();
	~GnsPolygon2();

public:
	void test01();
	void test02();

	/* --------------------------------------------------------------------------
	函数说明：判断两个浮点数是否相等
	传入参数：
		f1						浮点数1
		f2						浮点数2
		errorRange	误差范围，两个浮点数的差值的绝对值在此范围内，视为相等
	返回值：
		相等返回 true，不相等则返回 false
	-------------------------------------------------------------------------- */
	bool floatEqual(float f1, float f2, float errorRange=0.0001);

	// 取大值
	float maxFloat(float x, float y);

	// 取小值
	float minFloat(float x, float y);

	/* --------------------------------------------------------------------------
	函数说明：获得两个点的线段与X轴的夹角，即 p1到p0 的线段，线段是有方向的
	传入参数：
		p0			前一个点
		p1			后一个点
	返回值：
		pNext-->pPrev 的连线与X轴的夹角
	-------------------------------------------------------------------------- */
	float getAngleTwoPoint(VERTEX4 p0, VERTEX4 p1);

	/* --------------------------------------------------------------------------
	函数说明：根据 dx 和 dy 获得夹角
	传入参数：
		dx			在x轴的位移长度，是有方向的
		dy			在y轴的位移长度，是有方向的
	返回值：
		夹角
	-------------------------------------------------------------------------- */
	float getAngleTwoPoint(float  dx, float dy);

	/* --------------------------------------------------------------------------
	函数说明：初始化
	传入参数：
		rectWidth	    多边形在初始状态时所占矩形区域的宽度
		rectHeight 	多边形在初始状态时所占矩形区域的高度
		pots				多边形的顶点，是一个 VERTEX4 数组，注意：若此值赋0则默认为多边形是“多边形在初始状态时所占矩形区域”
		iPotCount      多边形的顶点数量，注意：若此值赋0则默认为多边形是“多边形在初始状态时所占矩形区域”
	-------------------------------------------------------------------------- */
	void init(int  rectWidth, int rectHeight, VERTEX4* pots=0, int iPotCount=0);

	/* --------------------------------------------------------------------------
	函数说明：初始化
	传入参数：
		rectWidth	    多边形在初始状态时所占矩形区域的宽度
		rectHeight 	多边形在初始状态时所占矩形区域的高度
		pots				多边形的顶点。
	-------------------------------------------------------------------------- */
	void init(int  rectWidth, int rectHeight, vector<VERTEX4> pots);

	/* --------------------------------------------------------------------------
	函数说明：相对移动，相对于上一个位置移动 dx 与 dy
	传入参数：
		dx	x轴的位移
		dy	y轴的位移
	备注：
	    需要手动计算位移差值，例如在 update 函数中：
			Vec2 curPos = _smallFish->getPosition();					// 当前位置
			Vec2 intervalPos = curPos - _prevPos;   // 位移差值
			_prevPos = curPos;   // 这一句很重要
	-------------------------------------------------------------------------- */
	int moveBy(float dx, float dy);

	/* --------------------------------------------------------------------------
	函数说明：设置多边形锚点的坐标位置，会自动移动多边形
	传入参数：
		x  多边形锚点的坐标的x轴位置，是绝对坐标位置非相对坐标位置
		x  多边形锚点的坐标的x轴位置，是绝对坐标位置非相对坐标位置
	返回值：
		位移有效返回 true，位移无效则返回 false
	-------------------------------------------------------------------------- */
	bool setPosition(float x, float y);

	/* --------------------------------------------------------------------------
	函数说明：设置多边形锚点的坐标位置，会自动移动多边形。通常是在沿 Bezier 曲线的切线方向移动时用到。
	传入参数：
		x  多边形锚点的坐标的x轴位置，是绝对坐标位置非相对坐标位置
		x  多边形锚点的坐标的x轴位置，是绝对坐标位置非相对坐标位置
	传出参数：
		willRotate  将要旋转的角度
	返回值：
		位移有效返回 true，位移无效则返回 false
	-------------------------------------------------------------------------- */
	bool setPositionEx(float x, float y, float& willRotate);

	/* --------------------------------------------------------------------------
	函数说明：相对顺时针旋转，在上一个角度的基础上顺时针旋转 angle 度（180度那种度）
	传入参数：
		angleInterval  旋转角度差值，相对于上一个位置旋转的角度（180度那种度）
	备注：
		需要手动计算位移差值，例如在 update 函数中：
			float  curRotateto = _smallFish->getRotation();		// 当前旋转角度
			float  intervalRotateto = curRotateto - _prevRotateto;   // 旋转角度差值
			_prevRotateto = curRotateto;  // 这一句很重要
	-------------------------------------------------------------------------- */
	int rotationZ_By(float angleInterval);

	// 获得多边形数组
	vector<VERTEX4>& getPots();

	/* --------------------------------------------------------------------------
	函数说明：设置多边形的旋转角度，会自动旋转多边形
	传入参数：
		angle  当前的顺时针旋转角度，是绝对角度而非相对角度
	返回值：
		旋转有效返回 true，旋转无效则返回 false
	-------------------------------------------------------------------------- */
	bool setAngle(float  angle);

	/* --------------------------------------------------------------------------
	函数说明：判断点是否在多边形内，只适用于凸多边形
	传入参数：
		p						点
		ptPolygon		多边形的点，是一个数组，
		nCount			多边形的点的数量
	传出参数：
	返回值：
		点在多边形内则返回 true，点不在多边形内返回false
	-------------------------------------------------------------------------- */
	bool pointInPolygon(MyPOINT p, MyPOINT* ptPolygon, int nCount);

	//// 另一种判断多边形顶点排列方向的方法      
	//bool isccwize(int ptCount, VERTEX4 vPolygon[]);

private:
//public:	// 测试用
	Mat44  _mat;

	const VERTEX4			_staticAnchor = VERTEX4(0.0f, 0.0f, 0.0f);		// 静止的锚点，其实就是假设这个点是父窗口的原点（通常是左下角的 0,0 点）
	vector<VERTEX4>	_vecStaticPot;	// 多边形的静止的点，即相对于静止的锚点的坐标
	RECT_VERTEX4			_staticRect;		// 静止的矩形框，以静止的锚点为中心点的矩形框，通常是父窗口的某个精灵图片的矩形

	VERTEX4						_anchor;		// 锚点，通常指变换后的锚点
	vector<VERTEX4>		_vecPot;		// 多边形的点，通常指变换后的点
	RECT_VERTEX4				_rect;			// 多边形的矩形框

	float   _xPrevAnchor=0;		// x轴上一次的锚点值
	float   _yPrevAnchor=0;		// y轴上一次的锚点值

	float  _prevAngle=0;			// 上一次的角度值

	float _PrevBezierAngle = 0;		// 上一个与x轴的角度，沿 Bezier 曲线的切线方向移动时
	float _curBezierAngle = 0;			// 当前与x轴的角度， 沿 Bezier 曲线的切线方向移动时
};

#endif